package io.pisceshub.muchat.server.util;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.ReflectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class BeanUtils {

    private static void handleReflectionException(Exception e) {
        ReflectionUtils.handleReflectionException(e);
    }

    public static <T, U> List<U> copyProperties(List<T> sourceList, Class<U> clazz) {

        if (sourceList == null || sourceList.size() <= 0) {
            return new ArrayList<>();
        }

        List<U> result = new ArrayList<>();
        for (T source : sourceList) {
            result.add(copyProperties(source, clazz));
        }

        return result;
    }

    /**
     * 如果source , 为空返回空对象
     *
     * @param sourceList
     * @param clazz
     * @return
     */
    public static <T, U> List<U> copyPropertiesList(List<T> sourceList, Class<U> clazz) {

        if (sourceList == null || sourceList.size() <= 0) {
            return new ArrayList<U>();
        }

        List<U> result = new ArrayList<>();
        U target = null;
        for (T source : sourceList) {
            try {
                target = clazz.newInstance();
                copyProperties(source, target);
            } catch (Exception e) {
                handleReflectionException(e);
                return new ArrayList<>();
            }
            result.add(target);
        }

        return result;
    }

    /**
     * source空为null
     *
     * @param orig
     * @param destClass
     * @param <T>
     * @return
     */
    public static <T> T copyProperties(Object orig, Class<T> destClass) {

        try {
            Object target = destClass.newInstance();
            if (orig == null) {
                return null;
            }
            copyProperties(orig, (Object) target);
            return (T) target;
        } catch (Exception e) {
            handleReflectionException(e);
            return null;
        }
    }

    /**
     * source 为null 返回 空对象
     *
     * @param orig
     * @param destClass
     * @param <T>
     * @return
     */
    public static <T> T copyProperty(Object orig, Class<T> destClass) {

        try {
            Object target = destClass.newInstance();
            if (orig == null) {
                return (T) target;
            }

            copyProperties(orig, (Object) target);
            return (T) target;
        } catch (Exception e) {
            handleReflectionException(e);
            Object o1 = new Object();
            try {
                o1 = destClass.newInstance();
            } catch (Exception ex) {
                handleReflectionException(e);
            }
            return (T) o1;
        }
    }

    public static <T, U> List<U> copyProperties(List<T> sourceList, Class<U> clazz,
                                                String... ignoreProperties) {

        if (sourceList == null || sourceList.size() <= 0) {
            return new ArrayList<U>();
        }

        List<U> result = new ArrayList<>();
        for (T source : sourceList) {
            result.add(copyProperties(source, clazz, ignoreProperties));
        }

        return result;
    }

    public static <T> T copyProperties(Object orig, Class<T> destClass, String... ignoreProperties) {

        if (orig == null) {
            return null;
        }

        try {
            Object target = destClass.newInstance();
            org.springframework.beans.BeanUtils.copyProperties(orig, (Object) target, ignoreProperties);
            return (T) target;
        } catch (Exception e) {
            return null;
        }
    }

    public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper beanWrapper = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] propDesc = beanWrapper.getPropertyDescriptors();

        Set<String> emptynames = new HashSet<String>();

        for (java.beans.PropertyDescriptor pd : propDesc) {
            Object srcValue = beanWrapper.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptynames.add(pd.getName());
            }
        }

        String[] result = new String[emptynames.size()];
        return emptynames.toArray(result);
    }

    public static void copyProperties(Object orig, Object dest) {
        try {
            org.springframework.beans.BeanUtils.copyProperties(orig, dest);
        } catch (Exception e) {
            handleReflectionException(e);
        }
    }

}
